"""
Prometheus指标导出器
实现ONVIF摄像头监控系统的Prometheus指标导出功能
"""

import threading
import time
from datetime import datetime
from typing import Dict, List, Optional, Any

from prometheus_client import (
    Gauge, Counter, Info, Histogram, Enum,
    start_http_server, CollectorRegistry, REGISTRY
)

from ..models.device import DeviceInfo, DeviceStatusRecord, DeviceStatus, NetworkMetrics
from ..utils.logger import get_logger

logger = get_logger(__name__)


class PrometheusExporter:
    """Prometheus指标导出器"""
    
    def __init__(self, port: int = 9090, host: str = "0.0.0.0", registry: CollectorRegistry = REGISTRY):
        self.port = port
        self.host = host
        self.registry = registry
        self.server_thread = None
        self.is_running = False
        self.start_time = time.time()
        
        # 初始化指标
        self._init_metrics()
        
        logger.info(f"Prometheus导出器初始化完成，端口: {port}")
    
    def _init_metrics(self):
        """初始化所有Prometheus指标"""
        
        # 设备基础信息指标
        self.device_info = Info(
            'onvif_device_info',
            'Device basic information',
            ['device_id'],
            registry=self.registry
        )
        
        # 设备状态指标
        self.device_online = Gauge(
            'onvif_device_online',
            'Device online status (1=online, 0=offline)',
            ['device_id', 'ip_address', 'manufacturer', 'model', 'status'],
            registry=self.registry
        )
        
        self.device_status = Enum(
            'onvif_device_status',
            'Device status enumeration',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            states=['online', 'offline', 'network_issue', 'service_issue', 'unknown'],
            registry=self.registry
        )
        
        # 设备发现时间指标
        self.device_first_discovered = Gauge(
            'onvif_device_first_discovered_timestamp',
            'Device first discovered timestamp',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            registry=self.registry
        )
        
        self.device_last_seen = Gauge(
            'onvif_device_last_seen_timestamp',
            'Device last seen timestamp',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            registry=self.registry
        )
        
        # 网络性能指标
        self.network_latency = Gauge(
            'onvif_network_latency_ms',
            'Network latency in milliseconds',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            registry=self.registry
        )
        
        self.network_jitter = Gauge(
            'onvif_network_jitter_ms',
            'Network jitter in milliseconds',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            registry=self.registry
        )
        
        self.packet_loss_rate = Gauge(
            'onvif_network_packet_loss_rate',
            'Packet loss rate percentage',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            registry=self.registry
        )
        
        # 网络延迟直方图
        self.latency_histogram = Histogram(
            'onvif_network_latency_histogram_ms',
            'Network latency distribution in milliseconds',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            buckets=[1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000],
            registry=self.registry
        )
        
        # 端口状态指标
        self.device_open_ports_count = Gauge(
            'onvif_device_open_ports_count',
            'Number of open ports on device',
            ['device_id', 'ip_address', 'manufacturer', 'model'],
            registry=self.registry
        )
        
        self.device_port_open = Gauge(
            'onvif_device_port_open',
            'Specific port status (1=open, 0=closed)',
            ['device_id', 'ip_address', 'manufacturer', 'model', 'port'],
            registry=self.registry
        )
        
        # 系统级指标
        self.monitor_start_time = Gauge(
            'onvif_monitor_start_time_timestamp',
            'Monitor system start time timestamp',
            registry=self.registry
        )
        
        self.monitor_uptime = Gauge(
            'onvif_monitor_uptime_seconds',
            'Monitor system uptime in seconds',
            registry=self.registry
        )
        
        self.monitor_cycles_total = Counter(
            'onvif_monitor_cycles_total',
            'Total number of monitoring cycles',
            registry=self.registry
        )
        
        self.monitor_errors_total = Counter(
            'onvif_monitor_errors_total',
            'Total number of monitoring errors',
            ['error_type'],
            registry=self.registry
        )
        
        # 设备统计指标
        self.devices_total = Gauge(
            'onvif_devices_total',
            'Total number of devices',
            registry=self.registry
        )
        
        self.devices_online_total = Gauge(
            'onvif_devices_online_total',
            'Number of online devices',
            registry=self.registry
        )
        
        self.devices_offline_total = Gauge(
            'onvif_devices_offline_total',
            'Number of offline devices',
            registry=self.registry
        )
        
        self.devices_network_issue_total = Gauge(
            'onvif_devices_network_issue_total',
            'Number of devices with network issues',
            registry=self.registry
        )
        
        self.devices_service_issue_total = Gauge(
            'onvif_devices_service_issue_total',
            'Number of devices with service issues',
            registry=self.registry
        )
        
        self.devices_unknown_total = Gauge(
            'onvif_devices_unknown_total',
            'Number of devices with unknown status',
            registry=self.registry
        )
        
        # 发现相关指标
        self.discovery_duration = Histogram(
            'onvif_discovery_duration_seconds',
            'Device discovery duration in seconds',
            buckets=[0.1, 0.5, 1, 2, 5, 10, 30, 60],
            registry=self.registry
        )
        
        self.devices_discovered_total = Counter(
            'onvif_devices_discovered_total',
            'Total number of devices discovered',
            registry=self.registry
        )
        
        # 设置系统启动时间
        self.monitor_start_time.set(self.start_time)
        
        logger.info("Prometheus指标初始化完成")
    
    def start_server(self):
        """启动HTTP指标服务器"""
        if self.server_thread is None or not self.server_thread.is_alive():
            self.server_thread = threading.Thread(
                target=self._start_server_thread,
                daemon=True,
                name="PrometheusServer"
            )
            self.server_thread.start()
            self.is_running = True
            logger.info(f"Prometheus指标服务器启动: http://{self.host}:{self.port}/metrics")
        else:
            logger.warning("Prometheus指标服务器已在运行")
    
    def _start_server_thread(self):
        """服务器线程"""
        try:
            start_http_server(self.port, self.host, registry=self.registry)
            logger.info(f"Prometheus HTTP服务器在 {self.host}:{self.port} 上启动成功")
        except Exception as e:
            logger.error(f"启动Prometheus HTTP服务器失败: {e}")
            self.is_running = False
    
    def stop_server(self):
        """停止服务器"""
        self.is_running = False
        logger.info("Prometheus指标服务器停止")
    
    def _get_device_labels(self, device_info: DeviceInfo) -> Dict[str, str]:
        """获取设备标签"""
        return {
            'device_id': device_info.device_id,
            'ip_address': device_info.ip_address,
            'manufacturer': device_info.manufacturer or 'Unknown',
            'model': device_info.model or 'Unknown'
        }
    
    def update_device_info(self, device_info: DeviceInfo):
        """更新设备基础信息指标"""
        try:
            labels = self._get_device_labels(device_info)
            
            # 更新设备信息
            info_data = {
                'ip_address': device_info.ip_address,
                'manufacturer': device_info.manufacturer or 'Unknown',
                'model': device_info.model or 'Unknown',
                'serial_number': device_info.serial_number or 'Unknown',
                'mac_address': device_info.mac_address or 'Unknown',
                'endpoint_url': device_info.endpoint_url,
                'port': str(device_info.port)
            }
            self.device_info.labels(device_id=device_info.device_id).info(info_data)
            
            # 更新发现时间
            if device_info.first_discovered:
                self.device_first_discovered.labels(**labels).set(
                    device_info.first_discovered.timestamp()
                )
            
            if device_info.last_seen:
                self.device_last_seen.labels(**labels).set(
                    device_info.last_seen.timestamp()
                )
            
            logger.debug(f"更新设备信息指标: {device_info.device_id}")
            
        except Exception as e:
            logger.error(f"更新设备信息指标失败: {e}")
            self.monitor_errors_total.labels(error_type='device_info_update').inc()
    
    def update_device_status(self, device_info: DeviceInfo, status_record: DeviceStatusRecord):
        """更新设备状态指标"""
        try:
            labels = self._get_device_labels(device_info)
            status_labels = {**labels, 'status': status_record.status.value}
            
            # 更新在线状态
            online_value = 1 if status_record.status == DeviceStatus.ONLINE else 0
            self.device_online.labels(**status_labels).set(online_value)
            
            # 更新状态枚举
            self.device_status.labels(**labels).state(status_record.status.value)
            
            # 更新网络指标
            if status_record.network_metrics:
                metrics = status_record.network_metrics
                
                self.network_latency.labels(**labels).set(metrics.latency_ms)
                self.network_jitter.labels(**labels).set(metrics.jitter_ms)
                self.packet_loss_rate.labels(**labels).set(metrics.packet_loss_rate)
                
                # 更新延迟直方图
                self.latency_histogram.labels(**labels).observe(metrics.latency_ms)
            
            # 更新端口信息
            if status_record.open_ports:
                self.device_open_ports_count.labels(**labels).set(len(status_record.open_ports))
                
                # 更新具体端口状态
                for port in status_record.open_ports:
                    port_labels = {**labels, 'port': str(port)}
                    self.device_port_open.labels(**port_labels).set(1)
            else:
                self.device_open_ports_count.labels(**labels).set(0)
            
            logger.debug(f"更新设备状态指标: {device_info.device_id} -> {status_record.status.value}")
            
        except Exception as e:
            logger.error(f"更新设备状态指标失败: {e}")
            self.monitor_errors_total.labels(error_type='device_status_update').inc()
    
    def update_system_metrics(self, stats: Dict[str, Any]):
        """更新系统级指标"""
        try:
            # 更新运行时间
            uptime = time.time() - self.start_time
            self.monitor_uptime.set(uptime)
            
            # 更新设备统计
            self.devices_total.set(stats.get('total_devices', 0))
            self.devices_online_total.set(stats.get('online_devices', 0))
            self.devices_offline_total.set(stats.get('offline_devices', 0))
            self.devices_network_issue_total.set(stats.get('network_issue_devices', 0))
            self.devices_service_issue_total.set(stats.get('service_issue_devices', 0))
            self.devices_unknown_total.set(stats.get('unknown_devices', 0))
            
            logger.debug("更新系统指标完成")
            
        except Exception as e:
            logger.error(f"更新系统指标失败: {e}")
            self.monitor_errors_total.labels(error_type='system_metrics_update').inc()
    
    def record_monitoring_cycle(self):
        """记录监控周期"""
        self.monitor_cycles_total.inc()
    
    def record_discovery_duration(self, duration: float):
        """记录发现耗时"""
        self.discovery_duration.observe(duration)
    
    def record_devices_discovered(self, count: int):
        """记录发现的设备数量"""
        self.devices_discovered_total.inc(count)
    
    def record_error(self, error_type: str):
        """记录错误"""
        self.monitor_errors_total.labels(error_type=error_type).inc()
    
    def get_metrics_url(self) -> str:
        """获取指标URL"""
        return f"http://{self.host}:{self.port}/metrics"
    
    def is_server_running(self) -> bool:
        """检查服务器是否运行"""
        return self.is_running and self.server_thread and self.server_thread.is_alive()

    def clear_device_metrics(self, device_info: DeviceInfo):
        """清理特定设备的所有metrics"""
        try:
            labels = self._get_device_labels(device_info)
            device_id = device_info.device_id

            logger.debug(f"开始清理设备metrics: {device_id}")

            # 清理设备基础信息指标
            try:
                self.device_info.labels(device_id=device_id).clear()
            except Exception as e:
                logger.debug(f"清理device_info失败: {e}")

            # 清理设备状态指标 - 需要包含status标签的所有组合
            status_values = ['online', 'offline', 'network_issue', 'service_issue', 'unknown']
            for status in status_values:
                try:
                    status_labels = {**labels, 'status': status}
                    self.device_online.remove(*status_labels.values())
                except Exception as e:
                    logger.debug(f"清理device_online[{status}]失败: {e}")

            # 清理设备状态枚举
            try:
                self.device_status.labels(**labels).clear()
            except Exception as e:
                logger.debug(f"清理device_status失败: {e}")

            # 清理时间戳指标
            try:
                self.device_first_discovered.remove(*labels.values())
            except Exception as e:
                logger.debug(f"清理device_first_discovered失败: {e}")

            try:
                self.device_last_seen.remove(*labels.values())
            except Exception as e:
                logger.debug(f"清理device_last_seen失败: {e}")

            # 清理网络性能指标
            try:
                self.network_latency.remove(*labels.values())
            except Exception as e:
                logger.debug(f"清理network_latency失败: {e}")

            try:
                self.network_jitter.remove(*labels.values())
            except Exception as e:
                logger.debug(f"清理network_jitter失败: {e}")

            try:
                self.packet_loss_rate.remove(*labels.values())
            except Exception as e:
                logger.debug(f"清理packet_loss_rate失败: {e}")

            # 清理端口相关指标
            try:
                self.device_open_ports_count.remove(*labels.values())
            except Exception as e:
                logger.debug(f"清理device_open_ports_count失败: {e}")

            # 清理具体端口状态 - 需要遍历可能的端口
            common_ports = [80, 443, 554, 8080, 8000, 8888, 9000]
            for port in common_ports:
                try:
                    port_labels = {**labels, 'port': str(port)}
                    self.device_port_open.remove(*port_labels.values())
                except Exception as e:
                    logger.debug(f"清理device_port_open[{port}]失败: {e}")

            logger.info(f"设备metrics清理完成: {device_id}")

        except Exception as e:
            logger.error(f"清理设备metrics失败: {e}")
            self.monitor_errors_total.labels(error_type='device_metrics_cleanup').inc()

    def clear_all_device_metrics(self):
        """清理所有设备相关的metrics"""
        try:
            logger.info("开始清理所有设备metrics")

            # 清理所有设备级指标
            # 注意：这是一个比较激进的方法，会清理所有设备相关的metrics

            # 清理设备信息指标
            try:
                self.device_info._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有device_info失败: {e}")

            # 清理设备状态指标
            try:
                self.device_online._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有device_online失败: {e}")

            try:
                self.device_status._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有device_status失败: {e}")

            # 清理时间戳指标
            try:
                self.device_first_discovered._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有device_first_discovered失败: {e}")

            try:
                self.device_last_seen._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有device_last_seen失败: {e}")

            # 清理网络性能指标
            try:
                self.network_latency._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有network_latency失败: {e}")

            try:
                self.network_jitter._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有network_jitter失败: {e}")

            try:
                self.packet_loss_rate._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有packet_loss_rate失败: {e}")

            # 清理延迟直方图
            try:
                self.latency_histogram._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有latency_histogram失败: {e}")

            # 清理端口相关指标
            try:
                self.device_open_ports_count._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有device_open_ports_count失败: {e}")

            try:
                self.device_port_open._metrics.clear()
            except Exception as e:
                logger.debug(f"清理所有device_port_open失败: {e}")

            logger.info("所有设备metrics清理完成")

        except Exception as e:
            logger.error(f"清理所有设备metrics失败: {e}")
            self.monitor_errors_total.labels(error_type='all_device_metrics_cleanup').inc()
